package com.icesoft.framework.core.util;

import com.icesoft.framework.core.util.functions.FunctionVoid2;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;

import java.util.*;
import java.util.function.Function;

/**
 * 树工具类
 * <pre>
 *     默认：
 *     父子关系：id->pid
 *     根节点：pid == null / pid == 0
 *     排序字段：sort
 *     转换：DozerUtil，源与目标字段名称一致
 *     子节点key：children
 * </pre>
 *
 * @author LKQ
 * @company 冰程【IceSoft】
 * @create 2022/9/7 6:58
 */
@SuppressWarnings("unused")
public class TreeUtil {
	public static final String DEF_KEY_SORT = "sort";
	public static String DEF_KEY_ID = "id";
	public static String DEF_KEY_PID = "pid";
	public static String DEF_KEY_NAME = "name";
	public static String DEF_KEY_CHILDREN = "children";

	public static int defSort(Object a, Object b) {
		Object v1 = ReflectionUtil.getFieldValue(a, DEF_KEY_SORT);
		Object v2 = ReflectionUtil.getFieldValue(b, DEF_KEY_SORT);
		if (Objects.isNull(v2)) {
			return 1;
		}
		if (v1 instanceof Integer) {
			return (int) v1 - (int) v2;
		}
		if (v1 instanceof Long) {
			return (int) ((long) v1 - (long) v2);
		}
		if (v1 instanceof String) {
			String str1 = String.valueOf(v1);
			String str2 = String.valueOf(v2);
			return str1.compareTo(str2);
		}
		return 0;
	}

	/**
	 * 构建字段一致树
	 *
	 * <pre>
	 *     除List子项外 源字段与目标字段一致，
	 * </pre>
	 *
	 * @param list   数据源
	 * @param clazz  目标对象class
	 * @param <T>    源泛型
	 * @param <Tree> 目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(@NonNull List<T> list, @NonNull Class<Tree> clazz) {
		return formatTree(list, clazz, DEF_KEY_CHILDREN);
	}

	/**
	 * 构建字段一致树
	 *
	 * <pre>
	 *     除List子项外 源字段与目标字段一致，
	 *     自定义子项key，
	 * </pre>
	 *
	 * @param list         数据源
	 * @param clazz        目标对象class
	 * @param childrenName 设置children的key 默认：children
	 * @param <T>          源泛型
	 * @param <Tree>       目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Class<Tree> clazz,
			@NonNull String childrenName
	) {
		return formatTree(list, clazz, DEF_KEY_ID, DEF_KEY_PID, childrenName);
	}

	/**
	 * 构建字段一致树
	 * <pre>
	 *     除List子项外 源字段与目标字段一致，
	 *     自定义子项key，
	 * </pre>
	 *
	 * @param list       数据源
	 * @param clazz      目标对象class
	 * @param isRootFunc 判读根节点函数
	 * @param <T>        源泛型
	 * @param <Tree>     目标泛型
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Class<Tree> clazz,
			@NonNull Function<T, Boolean> isRootFunc
	) {
		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>();
		return formatTree(list,
				isRootFunc,
				DEF_KEY_ID, DEF_KEY_PID,
				t -> DozerUtil.convert(t, clazz),
				bindChildrenFunction
		);
	}

	/**
	 * 构建字段一致树
	 *
	 * <pre>
	 *     除List子项外 源字段与目标字段一致，
	 *     自定义唯一标识
	 *     自定义关联标识
	 * </pre>
	 *
	 * @param list    数据源
	 * @param clazz   目标对象class
	 * @param idName  唯一标识名称
	 * @param pidName 关联字段名称
	 * @param <T>     源泛型
	 * @param <Tree>  目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Class<Tree> clazz,
			@NonNull String idName,
			@NonNull String pidName
	) {
		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>(DEF_KEY_CHILDREN);
		IsRootFunction<T> isRootFunction = new IsRootFunction<>(pidName);
		return formatTree(list,
				isRootFunction,
				idName, pidName,
				t -> DozerUtil.convert(t, clazz),
				bindChildrenFunction
		);
	}

	/**
	 * 构建字段一致树
	 *
	 * <pre>
	 *     除List子项外 源字段与目标字段一致，
	 *     自定义唯一标识
	 *     自定义关联标识
	 *     自定义子项key，
	 * </pre>
	 *
	 * @param list         数据源
	 * @param clazz        目标对象class
	 * @param idName       唯一标识名称
	 * @param pidName      关联字段名称
	 * @param childrenName 设置children的key 默认：children
	 * @param <T>          源泛型
	 * @param <Tree>       目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Class<Tree> clazz,
			@NonNull String idName,
			@NonNull String pidName,
			@NonNull String childrenName
	) {
		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>(childrenName);
		IsRootFunction<T> isRootFunction = new IsRootFunction<>(pidName);
		return formatTree(list,
				isRootFunction,
				idName, pidName,
				t -> DozerUtil.convert(t, clazz),
				bindChildrenFunction
		);
	}


	//===============================================================================

	/**
	 * 构建字段一致树
	 *
	 * <pre>
	 *     除List子项外 源字段与目标字段一致，
	 *     自定义根节点判断
	 *     自定义唯一标识
	 *     自定义关联标识
	 *     自定义子项key，
	 * </pre>
	 *
	 * @param list         数据源
	 * @param clazz        目标对象class
	 * @param isRootFunc   根节点判断 默认：值为null的是根节点
	 * @param idName       唯一标识名称
	 * @param pidName      关联字段名称
	 * @param childrenName 设置children的key 默认：children
	 * @param <T>          源泛型
	 * @param <Tree>       目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Class<Tree> clazz,
			@NonNull Function<T, Boolean> isRootFunc,
			@NonNull String idName,
			@NonNull String pidName,
			@NonNull String childrenName
	) {
		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>(childrenName);
		return formatTree(list,
				isRootFunc,
				idName, pidName,
				t -> DozerUtil.convert(t, clazz),
				bindChildrenFunction
		);
	}

	/**
	 * 自定义构建树
	 *
	 * <pre>
	 *     除List子项外 源字段与目标字段一致，
	 *     自定义根节点判断
	 *     自定义唯一标识
	 *     自定义关联标识
	 *     自定义子项key，
	 * </pre>
	 *
	 * @param list         数据源
	 * @param treeFunction 自定义树构建
	 * @param childrenName 设置children的key 默认：children
	 * @param <T>          源泛型
	 * @param <Tree>       目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull String childrenName
	) {

		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>(childrenName);
		return formatTree(list, treeFunction, bindChildrenFunction);
	}

	/**
	 * 自定义构建树
	 *
	 * @param list         数据源
	 * @param treeFunction 自定义构建
	 * @param <T>          源泛型
	 * @param <Tree>       目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Tree> treeFunction
	) {
		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>();
		return formatTree(list, treeFunction, bindChildrenFunction);
	}

	/**
	 * 自定义构建树
	 *
	 * <pre>
	 *     自定义根节点判断
	 * </pre>
	 *
	 * @param list           数据源
	 * @param treeFunction   自定义构建
	 * @param isRootFunction 根节点判断 默认：值为null的是根节点
	 * @param <T>            源泛型
	 * @param <Tree>         目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull Function<T, Boolean> isRootFunction
	) {
		NameFunction<T> idFunction = new NameFunction<>();
		NameFunction<T> pidFunction = new NameFunction<>();
		return formatTree(list, treeFunction, isRootFunction, idFunction, pidFunction);
	}

	/**
	 * 自定义构建树
	 *
	 * <pre>
	 *     自定义唯一标识
	 *     自定义关联标识
	 * </pre>
	 *
	 * @param list         数据源
	 * @param treeFunction 自定义构建
	 * @param idName       唯一标识名称
	 * @param pidName      关联字段名称
	 * @param <T>          源泛型
	 * @param <Tree>       目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull String idName,
			@NonNull String pidName
	) {
		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>(DEF_KEY_CHILDREN);
		return formatTree(list, idName, pidName, treeFunction, bindChildrenFunction);
	}

	/**
	 * 自定义构建树
	 *
	 * <pre>
	 *     自定义唯一标识
	 *     自定义关联标识
	 *     自定义子项key，
	 * </pre>
	 *
	 * @param list         数据源
	 * @param treeFunction 自定义构建
	 * @param idName       唯一标识名称
	 * @param pidName      关联字段名称
	 * @param childrenName 设置children的key 默认：children
	 * @param <T>          源泛型
	 * @param <Tree>       目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull String idName,
			@NonNull String pidName,
			@NonNull String childrenName
	) {
		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>(childrenName);
		return formatTree(list, idName, pidName, treeFunction, bindChildrenFunction);
	}

	/**
	 * 自定义构建树
	 *
	 * <pre>
	 *     自定义根节点判断
	 *     自定义唯一标识
	 *     自定义关联标识
	 *     自定义子项key，
	 * </pre>
	 *
	 * @param list           数据源
	 * @param treeFunction   自定义构建
	 * @param isRootFunction 根节点判断 默认：值为null的是根节点
	 * @param idName         唯一标识名称
	 * @param pidName        关联字段名称
	 * @param childrenName   设置children的key 默认：children
	 * @param <T>            源泛型
	 * @param <Tree>         目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull Function<T, Boolean> isRootFunction,
			@NonNull String idName,
			@NonNull String pidName,
			@NonNull String childrenName
	) {
		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>(childrenName);
		return formatTree(list, isRootFunction, idName, pidName, treeFunction, bindChildrenFunction);
	}

	/**
	 * 构建树 前提：
	 * 1.子父关系为 pid->id
	 * 2.根节点判断 pid == null/ pid == 0
	 * <pre>
	 *     static class Test {
	 *         Long id;
	 *         String name;
	 *         String text;
	 *         Long pid;
	 *     }
	 * </pre>
	 *
	 * @param list                 数据源
	 * @param treeFunction         构建节点数据
	 * @param bindChildrenFunction 绑定子项节点
	 * @param <T>                  源泛型
	 * @param <Tree>               目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull FunctionVoid2<Tree, Tree> bindChildrenFunction
	) {
		return formatTree(list,
				DEF_KEY_ID, DEF_KEY_PID,
				treeFunction, bindChildrenFunction
		);
	}

	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull String idName, @NonNull String pidName,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull FunctionVoid2<Tree, Tree> bindChildrenFunction
	) {
		IsRootFunction<T> isRootFunction = new IsRootFunction<>(pidName);
		return formatTree(list,
				isRootFunction,
				idName, pidName,
				treeFunction, bindChildrenFunction
		);
	}

	/**
	 * 构建树 前提：子父关系为 pid->id
	 * <pre>
	 *     static class Test {
	 *         Long id;
	 *         String name;
	 *         String text;
	 *         Long pid;
	 *     }
	 * </pre>
	 *
	 * @param list                 数据源
	 * @param isRootFunction       判断是根节点函数
	 * @param treeFunction         构建节点数据
	 * @param bindChildrenFunction 绑定子项节点
	 * @param <T>                  源泛型
	 * @param <Tree>               目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Boolean> isRootFunction,
			@NonNull String idName,
			@NonNull String pidName,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull FunctionVoid2<Tree, Tree> bindChildrenFunction
	) {
		NameFunction<T> idFunction = new NameFunction<>(idName);
		NameFunction<T> pidFunction = new NameFunction<>(pidName);
		return formatTree(list,
				treeFunction,
				isRootFunction,
				idFunction,
				pidFunction
		);
	}

	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull Function<T, Boolean> isRoot,
			@NonNull Function<T, Object> idFunction,
			@NonNull Function<T, Object> pidFunction
	) {
		BindChildrenFunction<Tree> bindChildrenFunction = new BindChildrenFunction<>();
		return formatTree(list, isRoot, idFunction, pidFunction, treeFunction, bindChildrenFunction);
	}

	/**
	 * 构建任意树
	 *
	 * <pre>
	 *     //原始结构
	 *     static class Test {
	 *         Long id;
	 *         String name;
	 *         String text;
	 *         Long pid;
	 *     }
	 *     //树结构
	 *     static class Tree {
	 *         Long id;
	 *         String name;
	 *         List<Tree> children;
	 *     }
	 *
	 *     List<Tree> treeList = formatTree(list, t -> t.getPid() == null,
	 *                 Test::getId,
	 *                 Test::getPid,
	 *                 //当结构一致可使用DozerUtil
	 *                 t-> DozerUtil.convert(t, Tree.class),
	 *                 //当结构不一致
	 *                 //t -> Tree.builder().id(t.getId()).name(t.getName()).build(),
	 *                 (r, item) -> ListHelper.add(r.getChildren(), i);
	 *         );
	 *
	 * </pre>
	 *
	 * @param list                 数据源
	 * @param isRoot               判断是根节点函数
	 * @param idFunction           唯一标识
	 * @param pidFunction          子项关联父项字段
	 * @param treeFunction         构建节点数据
	 * @param bindChildrenFunction 绑定子项节点
	 * @param <T>                  源泛型
	 * @param <Tree>               目标泛型
	 * @return List<Tree>
	 */
	public static <T, Tree> List<Tree> formatTree(
			@NonNull List<T> list,
			@NonNull Function<T, Boolean> isRoot,
			@NonNull Function<T, Object> idFunction,
			@NonNull Function<T, Object> pidFunction,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull FunctionVoid2<Tree, Tree> bindChildrenFunction
	) {
		List<T> rootList = new ArrayList<>();
		//重名的节点会覆盖，故该方法仅对不重复的数据进行构建树
		Map<Object, List<T>> map = new LinkedHashMap<>();
		for (T t : list) {
			if (isRoot.apply(t)) {
				rootList.add(t);
			} else {
				Object pid = pidFunction.apply(t);
				MapUtil.put(map, pidFunction.apply(t), t);
			}
		}
		//如果提供的查找根没找到根，使用快速查找法
		if (ListUtil.isEmpty(rootList)) {
			rootList = getPid(list, idFunction, pidFunction);
		}
		rootList.sort(TreeUtil::defSort);

		//绑定子节点
		List<Tree> trees = new ArrayList<>();
		for (T root : rootList) {
			Tree treeRoot = treeFunction.apply(root);
			bindChildren(root, treeRoot, map, idFunction, treeFunction, bindChildrenFunction);
			trees.add(treeRoot);
		}
		return trees;
	}

	/**
	 * 查找根结点
	 *
	 * @param list        数据
	 * @param idFunction  获取id函数
	 * @param pidFunction 获取pid函数
	 */
	public static <T> List<T> getPid(List<T> list,
									 @NonNull Function<T, Object> idFunction,
									 @NonNull Function<T, Object> pidFunction
	) {
		List<Object> idList = ListUtil.format(list, idFunction);
		List<Object> pidList = ListUtil.format(list, pidFunction);
		//pid不在当前数据中的数据就是根id
		pidList.removeAll(idList);
		List<T> ll = new ArrayList<>(list);
		//获取根数据
		ll.removeIf(t -> !pidList.contains(pidFunction.apply(t)));
		return ll;
	}

	/**
	 * 绑定子集
	 *
	 * @param root                 根节点
	 * @param treeRoot             树根节点
	 * @param map                  所有的子节点
	 * @param idFunction           唯一标识
	 * @param treeFunction         构建节点数据
	 * @param bindChildrenFunction 绑定子项节点
	 * @param <T>                  源泛型
	 * @param <Tree>               目标泛型
	 */
	private static <T, Tree> void bindChildren(
			@NonNull T root,
			@NonNull Tree treeRoot,
			@NonNull Map<Object, List<T>> map,
			@NonNull Function<T, Object> idFunction,
			@NonNull Function<T, Tree> treeFunction,
			@NonNull FunctionVoid2<Tree, Tree> bindChildrenFunction
	) {
		List<T> itemList = map.get(idFunction.apply(root));
		if (!Objects.isNull(itemList)) {
			for (T item : itemList) {
				Tree treeItem = treeFunction.apply(item);
				if (!Objects.isNull(treeItem)) {
					bindChildren(item, treeItem, map, idFunction, treeFunction, bindChildrenFunction);
					bindChildrenFunction.apply(treeRoot, treeItem);
				}
			}
		} else {
			bindChildrenFunction.apply(treeRoot, null);
		}
	}

	public static void main(String[] args) {
//        List<Test> list = Arrays.asList(
//                Test.builder().id(1L).pid(null).name("A").sort(2).text("哈哈1").build(),
//                Test.builder().id(2L).pid(null).name("A1").sort(2).text("哈哈2").build(),
//                Test.builder().id(3L).pid(1L).name("B1").sort(1).text("哈哈11").build(),
//                Test.builder().id(4L).pid(2L).name("A11").sort(1).text("哈哈22").build(),
//                Test.builder().id(5L).pid(3L).name("B11").sort(2).text("哈哈33").build(),
//                Test.builder().id(6L).pid(3L).name("B12").sort(1).text("哈哈44").build()
//        );

		//构造一致 《目标与源字段一致 除子项List以外》
//        List<TestTree> testTreeList = formatTree(list, TestTree.class,
//                t -> Objects.isNull(t.getPid()),
//                "id","pid","child");

//        List<TestTree> testTreeList = formatTree(list, TestTree.class,"id","pid","child");
//        List<TestTree> testTreeList = formatTree(list, TestTree.class,"id","pid");
//        List<TestTree> testTreeList = formatTree(list, TestTree.class,"child");


		//完全自定义构造
//        List<TestTree> testTreeList = formatTree(list,
//                t->TestTree.builder().id(t.getId()).name(t.getName()).build(),
//                t -> Objects.isNull(t.getPid()),
//                "id","pid","child");

//        List<TestTree> testTreeList = formatTree(list,
//                t->TestTree.builder().id(t.getId()).name(t.getName()).build(),
//                "id","pid","child");

//        List<TestTree> testTreeList = formatTree(list,
//                t->TestTree.builder().id(t.getId()).name(t.getName()).build(),
//                "id","pid");

//        List<TestTree> testTreeList = formatTree(list,
//                t->TestTree.builder().id(t.getId()).name(t.getName()).build(),
//                "child");

//        List<TestTree> testTreeList = formatTree(list,
//                t -> TestTree.builder().id(t.getId()).name(t.getName()).build(),
//                t->Objects.isNull(t.getPid())
//        );

//        List<TestTree> testTreeList = formatTree(list,
//                t -> TestTree.builder().id(t.getId()).name(t.getName()).build());


//        List<TestTree> testTreeList = formatTree(list,
//                t -> TestTree.builder().id(t.getId()).name(t.getName()).build(),
//                t -> Objects.isNull(t.getPid()),
//                t -> t.getId() + "_" + t.getPid(),
//                Test::getPid
//        );

//        List<TestTree> testTreeList = formatTree(list, TestTree.class);


//        List<TestTree> testTreeList = formatTree(list,
//                t -> Objects.isNull(t.getPid()), //根判断
//                Test::getId,//唯一标识
//                Test::getPid,//关联字段
//                t -> TestTree.builder().id(t.getId()).name(t.getName()).build(),//自定义构建tree
//                (r, i) -> {//自定义设置子项
//                    if (Objects.isNull(r.getChildren())) {
//                        r.setChildren(new ArrayList<>());
//                    }
//                    r.getChildren().add(i);
//                }
//        );
//        System.out.println(testTreeList);
	}

	/**
	 * 自定义绑定名称 反射处理绑定关系 默认使用children，children没有返回null
	 */
	@Data
	@NoArgsConstructor
	@AllArgsConstructor
	public static class BindChildrenFunction<Tree> implements FunctionVoid2<Tree, Tree> {
		private String childrenKey = DEF_KEY_CHILDREN;

		@SuppressWarnings("unchecked")
		@Override
		public void apply(Tree root, Tree item) {
			if (!Objects.isNull(item)) {
				Object val = ReflectionUtil.getFieldValue(root, getChildrenKey());
				List<Tree> itemList = new ArrayList<>();
				if (!Objects.isNull(val)) {
					itemList = (List<Tree>) val;
				}
				itemList.add(item);

				if (ReflectionUtil.isContainFieldName(item.getClass(), DEF_KEY_SORT)) {
					itemList.sort(TreeUtil::defSort);
				}

				ReflectionUtil.setFieldValue(root, getChildrenKey(), itemList);
			}
		}
	}

	/**
	 * 自定义绑定名称 反射处理绑定关系 默认使用children，children没有返回[]
	 */
	@Data
	@NoArgsConstructor
	@AllArgsConstructor
	static class BindChildrenDefArrayFunction<Tree> implements FunctionVoid2<Tree, Tree> {
		private String childrenKey = DEF_KEY_CHILDREN;

		@SuppressWarnings("unchecked")
		@Override
		public void apply(Tree root, Tree item) {
			Object val = ReflectionUtil.getFieldValue(root, getChildrenKey());
			List<Tree> itemList = new ArrayList<>();
			if (!Objects.isNull(val)) {
				itemList = (List<Tree>) val;
			}
			if (!Objects.isNull(item)) {
				itemList.add(item);
			}
			ReflectionUtil.setFieldValue(root, getChildrenKey(), itemList);
		}
	}

	/**
	 * 自定义获取名称数据函数
	 */
	@Data
	@NoArgsConstructor
	@AllArgsConstructor
	public static class NameFunction<T> implements Function<T, Object> {
		String name;

		@Override
		public Object apply(T t) {
			return ReflectionUtil.getFieldValue(t, getName());
		}
	}

	@Data
	@NoArgsConstructor
	@AllArgsConstructor
	public static class TreeFunction<T, TREE> implements Function<T, TREE> {
		Class<TREE> clazz = ReflectionUtil.getClass(this.getClass(), 1);

		@Override
		public TREE apply(T t) {
			return DozerUtil.convert(t, getClazz());
		}
	}

	/**
	 * 判断是根节点函数
	 * <pre>
	 * 字段为null/0的
	 * </pre>
	 */
	@Data
	@NoArgsConstructor
	@AllArgsConstructor
	public static class IsRootFunction<T> implements Function<T, Boolean> {
		String name;

		@Override
		public Boolean apply(T t) {
			Object val = ReflectionUtil.getFieldValue(t, getName());
			if (Objects.isNull(val)) {
				return true;
			}
			if (val instanceof Integer) {
				Integer num = NumberUtil.intValueOf0(val);
				return num == 0;
			}
			if (val instanceof Long) {
				Long num = NumberUtil.longValueOf0(val);
				return num == 0L;
			}
			if (val instanceof Double) {
				Double num = NumberUtil.doubleValueOf0(val);
				return num == 0D;
			}
			return false;
		}
	}

}
